﻿using System;
using System.CodeDom.Compiler;
using DhbInterfaces;

namespace FunctionalCLR.Core
{
    public class IOneVariableFunctionCompiler
    {
        CodeDomProvider m_Provider = null;
        CompilerParameters m_CompilerParameters = null;

        private IFunctionManager funcMgr = null;

        public IOneVariableFunctionCompiler()
        {
            // Create the compiler
            m_Provider = new Microsoft.CSharp.CSharpCodeProvider();
            // Set the parameters of the compiler
            m_CompilerParameters = new CompilerParameters(
                new string[] { 
                    "System.dll",
                    "DhbInterfaces.dll",
                    this.GetType().Assembly.Location
                });
            m_CompilerParameters.GenerateInMemory = true;
            m_CompilerParameters.GenerateExecutable = false;
        }

        public IOneVariableFunctionCompiler(IFunctionManager funcMgr)
            : this()
        {
            this.funcMgr = funcMgr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="root"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public IOneVariableFunction Parse(Node root, string param)
        {
            UnaryFunctionTranslator uft
            = new UnaryFunctionTranslator(
                this.funcMgr, param);
            string fexpr = uft.Translate(root);

            IOneVariableFunctionCompiler compiler =
                new IOneVariableFunctionCompiler();

            IOneVariableFunction func = compiler.Parse(fexpr);

            return func;
        }

        public IOneVariableFunction Parse(string expr)
        {
            //CheckExpression(ref expr);
            string src =
                "using System;using DhbInterfaces;"
                + "class MyFunctionClass : IOneVariableFunction"
                + "{" + "public MyFunctionClass(){}" + "public double Value(double x)"
                + "{" + "return " + expr + ";" + "}" + "}";

            CompilerResults results = m_Provider.CompileAssemblyFromSource(
                m_CompilerParameters, src);
            Console.WriteLine(src);
            if (results.Errors.Count == 0 && results.CompiledAssembly != null)
            {
                Type ObjType = results.CompiledAssembly.GetType("MyFunctionClass");
                IOneVariableFunction func = null;

                if (ObjType != null)
                {
                    func = Activator.CreateInstance(ObjType) as IOneVariableFunction;
                }

                return func;
            }
            else throw new Exception(results.Errors[0].ToString());
        }
    }
}
